/*****************************************************************************/
/**
 *  @file   main.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include <iostream>
#include <string>
#include <util/SPHFileList.h>
#include <util/ImportSPHFile.h>
#include <kvs/Math>
#include <kvs/glut/Application>
#include <kvs/glut/Screen>
#include <kvs/Bounds>
#include <kvs/PointObject>
#include <kvs/LineObject>
#include <kvs/PolygonObject>
#include <kvs/StructuredVolumeObject>
#include <kvs/ExternalFaces>


namespace
{

kvs::Vector3f ToVec3( const kvs::Vector3d& v )
{
    return kvs::Vector3f( (float)v.x(), (float)v.y(), (float)v.z() );
}

kvs::Vector3f Min( const kvs::Vector3f& a, const kvs::Vector3f& b )
{
    return kvs::Vector3f(
        kvs::Math::Min( a[0], b[0] ),
        kvs::Math::Min( a[1], b[1] ),
        kvs::Math::Min( a[2], b[2] ) );
}

kvs::Vector3f Max( const kvs::Vector3f& a, const kvs::Vector3f& b )
{
    return kvs::Vector3f(
        kvs::Math::Max( a[0], b[0] ),
        kvs::Math::Max( a[1], b[1] ),
        kvs::Math::Max( a[2], b[2] ) );
}

}

int main( int argc, char** argv )
{
    kvs::glut::Application app( argc, argv );
    kvs::glut::Screen screen( &app );
    screen.show();

    std::string dirname( argv[1] );
    kvsbloodvis::util::SPHFileList sph_list( dirname );
    sph_list.print( std::cout );

    kvs::Vector3f global_region_min = kvs::Vector3f::All( kvs::Value<kvs::Real32>::Max() );
    kvs::Vector3f global_region_max = kvs::Vector3f::All( kvs::Value<kvs::Real32>::Min() );

    for ( size_t i = 0; i < sph_list.size(); i++ )
    {
        const kvsbloodvis::util::SPHFile& sph = sph_list.sph(i);

        kvs::Vector3f local_region_min = ::ToVec3( sph.org() );
        kvs::Vector3f local_region_max = ::ToVec3( sph.org() + sph.max() * sph.pitch() );
        global_region_min = ::Min( global_region_min, local_region_min );
        global_region_max = ::Max( global_region_max, local_region_max );

        kvs::StructuredVolumeObject volume = kvsbloodvis::util::ImportSPHFile( sph );
        kvs::PolygonObject* object = new kvs::ExternalFaces( &volume );
        object->setMinMaxExternalCoords( local_region_min, local_region_max );

        kvs::Bounds bounds;
        bounds.setLineWidth( 1.0f );
        bounds.setLineColor( kvs::RGBColor::Red() );

        screen.registerObject( object );
        screen.registerObject( bounds.outputLineObject( object ) );
    }

    {
        kvs::PointObject dummy;
        dummy.setMinMaxObjectCoords( global_region_min, global_region_max );
        dummy.setMinMaxExternalCoords( global_region_min, global_region_max );

        kvs::Bounds bounds;
        bounds.setLineWidth( 2.0f );
        bounds.setLineColor( kvs::RGBColor::Black() );

        screen.registerObject( bounds.outputLineObject( &dummy ) );
    }

    return app.run();
}
